package handler;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 * Saves/Reads compressed xml files from the filesystem
 * @author Jared Schlicht
 */
public class CompressedXMLDAO implements NotebookDAO {
    private XMLHandler xmlHandler;
    private CompressionHandler compressionHandler;
    private String filename;
    
    /**
     * Constructs a new CompressedXMLDAO object for the specified filename.
     * 
     * @author Jared Schlicht
     * @param filename file to read/write from
     */
    public CompressedXMLDAO(String filename) {
        this.filename = filename;
        this.xmlHandler = new XMLHandler();
        this.compressionHandler = new CompressionHandler();
    }
    
    /**
     * Gets a list of equations from the compressed file
     * @author Jared Schlicht
     */
    @Override
    public List<EquateNode> getEquations() {
        InputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(this.filename);
            // decompress the file in RAM first
            ByteArrayOutputStream decompressedOutputStream = new ByteArrayOutputStream();
            this.compressionHandler.decompress(fileInputStream, decompressedOutputStream);
            
            // feed the decompressed data to the XML Handler
            ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(decompressedOutputStream.toByteArray());
            
            return this.xmlHandler.getEquations(xmlInputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();                    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }            
        }
    }

    /**
     * Writes the equations to a compressed XML file.
     * 
     * @author Jared Schlicht
     */
    @Override
    public void saveEquations(List<EquateNode> notebookEquations) {
        OutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(this.filename);
            // convert the list to XML in memory first
            ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
            this.xmlHandler.saveEquations(notebookEquations, xmlOutputStream);
            
            // compress the XML that's currently sitting in memory
            ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xmlOutputStream.toByteArray());
            
            this.compressionHandler.compress(xmlInputStream, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();                    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }            
        }
    }
}
